﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Common.Extensions;
using Contact.DAL.Models.Worktime;
using EFDataModel;
using TimeManagement;

namespace ContactMvc4TB.Models.Worktime.Helpers
{
    public class StatisticWorktimeData
    {
        #region Properties
        /// <summary>
        /// Die UserId für die die Daten ermittelt werden soll
        /// </summary>
        private long UserId { get; set; }

        /// <summary>
        /// Pausenzeit in Minuten
        /// </summary>
        public int BreaktimeInMinutes { get; set; }

        /// <summary>
        /// Die Arbeitszeit in Minuten
        /// </summary>
        public int WorktimeInMinutes { get; set; }

        /// <summary>
        /// Die Krankheitszeit in Minuten
        /// </summary>
        public int IllnesTimeInMinutes { get; set; }

        /// <summary>
        /// Die Urlaubszeit in Minuten
        /// </summary>
        public int HolidayTimeInMinutes { get; set; }

        /// <summary>
        /// Unserer bisheriger Jahresurlaub in Minuten
        /// </summary>
        public int CurrentYearlyHollidayTimesInMinutes { get; set; }

        /// <summary>
        /// Die Anzahl der Urlaubstage für das jeweilige Jahr.
        /// </summary>
        public int YearHolidayTimesInMinutes { get; set; }

        /// <summary>
        /// Die Gesamtprojektzeit in Minuten
        /// </summary>
        public int ProjectTimeInMinutes { get; set; }

        /// <summary>
        /// Die Weiterbildungszeit in Minuten
        /// </summary>
        public int QualificationTimeInMinutes { get; set; }

        /// <summary>
        /// Die Monatliche Arbeitszeit in Minuten
        /// </summary>
        public int MonthlyWorktimeInMinutes { get; set; }

        /// <summary>
        /// Die bisher geleistete Monatliche Arbeitszeit.
        /// </summary>
        public int CurrentMonthlyWorktimeInMinutes { get; set; }

        /// <summary>
        /// Die Gesamten bisherigen Überstunden
        /// </summary>
        public long OverAllOvertime { get; set; }

        /// <summary>
        /// Die Überstunden für den aktuellen Monat
        /// </summary>
        public int CurrentMonthOverTime { get; set; }

        /// <summary>
        /// Die aktuelle Monatliche Krankheitszeit.
        /// </summary>
        public int CurrentMonthlyIllnesstimeInMinutes { get; set; }

        /// <summary>
        /// Die Krankheitszeit für das aktuelle Jahr.
        /// </summary>
        public int CurrentYearlyIllnesstimeInMinutes { get; set; }

        /// <summary>
        /// Noch offene Arbeitstage für die noch keine Arbeitszeit eingetragen wurde.
        /// </summary>
        public int OpenWorkingDays { get; set; }

        /// <summary>
        /// Die Tägliche Arbeitszeit die mindestsn gearbeitet werden muss in Minuten
        /// </summary>
        public int DailyWorktimeInMinutes { get; set; }

        /// <summary>
        /// Die Überstunden für den aktuellen Tag ermitteln.
        /// </summary>
        public int CurrentDayOverTime { get; set; }

        /// <summary>
        /// Gibt die Tage zurück an denen kein Arbeitszeiteintrag gefunden werden konnte.
        /// </summary>
        public int CurrentNoWorktimeEntryFoundDays { get; set; }
        #endregion

        #region Konstruktor
        public StatisticWorktimeData(long userId)
        {
            UserId = userId;
            BreaktimeInMinutes = 0;
            WorktimeInMinutes = 0;
            IllnesTimeInMinutes = 0;
            HolidayTimeInMinutes = 0;
            ProjectTimeInMinutes = 0;
            QualificationTimeInMinutes = 0;
        }
        #endregion

        #region Public Functions
        /// <summary>
        /// die passenden Statistikdaten für das übergebene Datum laden und berechnen.
        /// </summary>
        /// <param name="date">Das Datum für das die Statistikdaten geladen werden sollen.</param>
        public void LoadStatisticData(DateTime date)
        {
            WorktimeRepository worktimeRepository = new WorktimeRepository(CurrentHttpContext.GetDataModel());
            WorktimeSettingsRepository worktimeSettingsRepository = new WorktimeSettingsRepository(CurrentHttpContext.GetDataModel());
            EFWorktimeSetting worktimeSetting = worktimeSettingsRepository.LoadWorktimeSetting(UserId);
            //Die Liste nur einmal aus der DB abrufen.
            EFWorktime worktimeToday = worktimeRepository.GetWorktime(UserId, date);
            if (worktimeToday != null)
            {
                BreaktimeInMinutes = worktimeToday.Breaktime;
                WorktimeInMinutes = worktimeToday.Worktime;
                IllnesTimeInMinutes = worktimeToday.Illness;
                HolidayTimeInMinutes = worktimeToday.Holidaytime;
                ProjectTimeInMinutes = worktimeToday.Projecttime;
                QualificationTimeInMinutes = worktimeToday.Qualificationtime;
                DailyWorktimeInMinutes = worktimeToday.DailyWorktime;
                CurrentDayOverTime = worktimeToday.ManualOvertime + worktimeToday.Overtime;
            }
            else
            {
                //Wenn für den Tag noch kein Arbeitszeiteintrag existiert, dann die Arbeitszeit z.b. aus den Settings laden.
                DailyWorktimeInMinutes = TimeFunctions.DailyWorktimeInMinutes(worktimeSetting.EFAuthentication.EFWorktimeSetting);
            }

            //Alle Arbeitszeiten für den übergebenen Monat im Datum ermitteln
            List<EFWorktime> worktimesMonth = worktimeRepository.GetWorktimeByMonth(UserId, date).ToList();
            MonthlyWorktimeInMinutes = TimeManagement.TimeManagement.GetMonthlyWorktimeInMinutes(worktimeSetting, date, worktimesMonth);
            CurrentMonthlyWorktimeInMinutes = worktimesMonth.Sum(p => p.Worktime);
            CurrentMonthOverTime = worktimesMonth.Sum(p => p.Overtime) + worktimesMonth.Sum(p => p.ManualOvertime);
            CurrentMonthlyIllnesstimeInMinutes = worktimesMonth.Sum(p => p.Illness);
            //Ermittelt alle Arbeitszeiteinträge des übergebenen Jahres
            List<EFWorktime> worktimesYear = worktimeRepository.GetWorktime(UserId, date.FirstDayOfYear(), date.LastDayOfYear()).ToList();
            CurrentYearlyIllnesstimeInMinutes = worktimesYear.Sum(p => p.Illness);
            CurrentYearlyHollidayTimesInMinutes = worktimesYear.Sum(p => p.Holidaytime);

            //Ermittelt den Gesamturlaub für das aktuelle Jahr in Minuten
            HolidayDays holidayDays = worktimeSettingsRepository.LoadHolidayDays(UserId, date.Year);
            YearHolidayTimesInMinutes = holidayDays != null ? (int)(holidayDays.Days*DailyWorktimeInMinutes) : 0;
            
            //Alle Arbeitszeiteinträge des Users ermitteln
            List<EFWorktime> worktimes = worktimeRepository.GetWorktimeList(UserId).ToList();
            int over = worktimes.Sum(p => p.ManualOvertime);
            OverAllOvertime = worktimes.Sum(p => p.Overtime) + worktimes.Sum(p => p.ManualOvertime);

            CalculateNoWorktimeEntryDays calculate = new CalculateNoWorktimeEntryDays(UserId);
            CurrentNoWorktimeEntryFoundDays = calculate.CountNoWorktimeEntryDays();
        }
        #endregion
    }
}